package com.ganbo.rabbitmq.producer.config;

import com.ganbo.rabbitmq.common.enums.MessageStatus;
import com.ganbo.rabbitmq.producer.entity.ProducerMessage;
import com.ganbo.rabbitmq.producer.repository.ProducerMessageRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@Slf4j
public class RabbitMqConfig {

    @Autowired
    private CachingConnectionFactory connectionFactory;
    @Autowired
    ProducerMessageRepository producerMessageRepository;

    @Bean
    public RabbitTemplate rabbitTemplate() {
        //设置消息发送确认机制-生产确认
        connectionFactory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED);
        //设置消息发送确认机制-发送成功时返回反馈消息
        connectionFactory.setPublisherReturns(true);

        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        rabbitTemplate.setMandatory(true);

        //设置消息发送回调监听
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
                    if (ack) {
                        log.info("消息发送成功: correlationData:{}, ack:{},cause:{}", correlationData, ack, cause);
                        String messageId = correlationData.getId();
                        ProducerMessage message = producerMessageRepository.findByMessageId(messageId);
                        message.setStatus(MessageStatus.e2.getCode());
                        producerMessageRepository.saveAndFlush(message);
                        log.info("更新本地消息成功");
                    } else {
                        log.info("=====消息发送失败: correlationData:{}, ack:{},cause:{}", correlationData, ack, cause);
                    }
                }
        );

        //设置消息路由发送失败回调监听(比如路由健错误导致找不到相应接收的队列)
        rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
            log.info("消息发送失败: message:{}, replyCode:{},replyText:{},exchange:{},routingKey:{}", message, replyCode, replyText, exchange, routingKey);
        });

        return rabbitTemplate;
    }

}
